﻿using System;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;

namespace Trentacular.SharePoint.SmartEditorPart.Web.UI.WebParts
{
    public class UserControlEditorPart<T> : BaseEditorPart<T> where T : WebPart
    {
        /// <summary>
        /// Virtual path to a UserControl that this EditorPart should wrap.
        /// The user control will be loaded when CreateChildControls is invoked, set
        /// on the EditorControl property, and added to the Controls collection.
        /// </summary>
        /// <value>The user control virtual path.</value>
        public string UserControlVirtualPath { get; private set; }

        /// <summary>
        /// Initializes a new instance of the
        /// <see cref="UserControlEditorPart&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="wrappedUserControlVirtualPath">The user control
        /// virtual path.  THe UserControl must implement
        /// <see cref="IWebPartEditor<T>" />.</param>
        public UserControlEditorPart(string userControlVirtualPath)
        {
            this.UserControlVirtualPath = userControlVirtualPath;
        }

        /// <summary>
        /// Gets the editor control.
        /// </summary>
        /// <value>The editor control.</value>
        public IWebPartEditor<T> EditorControl { get; private set; }

        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use
        /// composition-based implementation to create any child controls they contain
        /// in preparation for posting back or rendering.
        /// </summary>
        protected override void CreateChildControls()
        {
            var control = Page.LoadControl(this.UserControlVirtualPath);
            var editorControl = control as IWebPartEditor<T>;
            
            if (editorControl == null)
                throw new ArgumentException(
                    string.Format(
                        "The UserControl specified at path '{0}' does not implement '{1}'",
                        this.UserControlVirtualPath,
                        typeof(IWebPartEditor<T>).FullName)
                    );

            editorControl.WebPartToEdit = this.WebPartToEdit;
            this.EditorControl = editorControl;

            this.Controls.Add(control);
        }

        /// <summary>
        /// Saves the values in an
        /// <see cref="T:System.Web.UI.WebControls.WebParts.EditorPart"/> control to the
        /// corresponding properties in the associated
        /// <see cref="T:System.Web.UI.WebControls.WebParts.WebPart"/> control.
        /// </summary>
        /// <returns>
        /// true if the action of saving values from the
        /// <see cref="T:System.Web.UI.WebControls.WebParts.EditorPart"/> control to the
        /// <see cref="T:System.Web.UI.WebControls.WebParts.WebPart"/> control is
        /// successful; otherwise (if an error occurs), false.
        /// </returns>
        public override bool ApplyChanges()
        {
            EnsureChildControls();
            return this.EditorControl.ApplyChanges();
        }

        /// <summary>
        /// Retrieves the property values from a
        /// <see cref="T:System.Web.UI.WebControls.WebParts.WebPart"/> control for its
        /// associated <see cref="T:System.Web.UI.WebControls.WebParts.EditorPart"/>
        /// control.
        /// </summary>
        public override void SyncChanges()
        {
            EnsureChildControls();
            this.EditorControl.SyncChanges();
        }
    }
}
